#include "person.h"
#include "building.h"   // We needs to do this to avoid a circular declaration problem
#include "levelscene.h"


Person::Person(PathMap *mapper, QPixmap personPixmap, LevelScene *parent, QGraphicsScene *scene)
    : QGraphicsPixmapItem(personPixmap)
{
    scene->addItem(this);
    setData(ITEM_TYPE,GameItems::Person);

    overlayPixmap = personPixmap;
    overlayPixmap.fill(QColor(42,255,0,128));
    overlayPixmap.setAlphaChannel(pixmap().alphaChannel());

    setOffset(-(pixmap().width()/2),-(pixmap().height()/2));

    virus = 0;

    // Create the stats object for the person
    stats = new PersonStats();

    currentBuilding = 0;

    pathMap = mapper;
    pathLocation = 0;

    parentScene = parent;

    inBuilding = true;
    setVisible(false);

}

void Person::timerEvent(QTimerEvent *)
{
    killTimer(timerID);

    int x,y;

    if (path.size()>0)  // if we have a path, set the starting location to the precious node, else set it to the current location of the person
    {
        pathMap->StateToXY(path.at(pathLocation-1),x,y);
        path.clear();
        pathLocation = 0;
    }
    else
    {
        x = pos().x()/10;
        y = pos().y()/10;
    }

    parentScene->leaveBuilding(this, currentBuilding);

    //get a new random building that is not the building we are in right now
    int newBuildingID = (rand() % parentScene->buildings.length());
    while (currentBuilding == parentScene->buildings.at(newBuildingID))
        newBuildingID = (rand() % parentScene->buildings.length());

    currentBuilding = parentScene->buildings.at(newBuildingID);
    emit solvePath(QPoint(x,y),currentBuilding->getEnterencePoint(),this);
    setVisible(true);
    inBuilding = false;
}

void Person::startPerson()
{
    if (inBuilding)
        timerID = startTimer(rand() % 30000);
}

void Person::stopPerson()
{
    if (inBuilding)
        killTimer(timerID);
}

void Person::treatPerson()
{
    //Something will eventually happen here
}

void Person::advance(int phase)
{
    if (phase == 0)
    {
        //Move person along path
        if (path.size() > 0)
        {
            if ((unsigned int)(pathLocation + 1) < path.size())
            {
                int x,y;
                pathMap->StateToXY(path.at((int)pathLocation),x,y);
                //qDebug("x: %d, y: %d\n",x,y);
                if (pathMap->IsPointPassable(x,y))
                {
                    int prevX, prevY, nextX, nextY;
                    double localMovement;

                    pathMap->StateToXY(path.at((int)pathLocation), prevX, prevY);
                    pathMap->StateToXY(path.at((int)pathLocation + 1), nextX, nextY);
                    localMovement = pathLocation - (int)pathLocation;

                    double moveX, moveY;
                    moveX = localMovement * (nextX - prevX);
                    moveY = localMovement * (nextY - prevY);

                    setPos((moveX + prevX) * 10, (moveY + prevY) * 10);
                    pathLocation += 0.125;
                }
                else
                {
                    // if we run into a road block, turn around and find a new building
                    timerID = startTimer(0);
                }
            }

            if ((pathLocation > path.size()-2) && (path.size()>0))
                arrive();
        }
    }
}

bool Person::GetInBuilding()
{
    return inBuilding;
}

void Person::collidesWithPerson(Person *colliding)
{

    //Transmit the virus
    if(virus != 0 && colliding->virus == 0
       && (rand() % 1000) + (virus->Infectivity * stats->resistenceGetter()) > 1000)
    {
        colliding->virus = new Virus(virus->Virulence, virus->Infectivity, virus->DrugResistance, virus->ImmuneResistance, virus->Hp, this);
    }
    else if(colliding->virus != 0 && virus == 0
        && (rand() % 1000) + (colliding->virus->Infectivity * stats->resistenceGetter()) > 1000)
    {
        virus = new Virus(colliding->virus->Virulence, colliding->virus->Infectivity, colliding->virus->Infectivity, colliding->virus->ImmuneResistance, colliding->virus->Hp, this);
    }
}

Building * Person::getCurrentBuilding()
{
    return currentBuilding;
}

void Person::setCurrentBuilding(Building *newBuilding)
{
    currentBuilding = newBuilding;
}

bool Person::isInBuilding()
{
    return inBuilding;
}

void Person::setPath(std::vector<void *>newPath)
{
    if (newPath.size() == 0)    // if the path is empty, then go to a new building.
        timerID = startTimer(0);
    path = newPath;
}

void Person::arrive()
{
    parentScene->enterBuilding(this,currentBuilding);
    setVisible(false);
    inBuilding = true;
    pathLocation = 0;
    path.clear();
    timerID = startTimer(20000 + ((rand() % 16000)-8000));
}

void Person::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QGraphicsPixmapItem::paint(painter,option,widget);

    if (virus != 0)
        painter->drawPixmap(offset(),overlayPixmap);
}
